package org.alex.sample.AOP;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class LogAspect {

	private static final String pointcut = "execution(* org.alex.sample.dao.Impl.IUserDAOImpl.*(..))";
	
	@Before(pointcut)
	public void beforeLog() {
		System.out.println("beforeLog-------------前置通知");
	}
	
	@After(pointcut)
	public void afterLog(JoinPoint point) {
		System.out.println("afterLog--------------最终通知");
		System.out.println("afterLog-------------目标方法为：" + point.getSignature().getDeclaringTypeName() + "."
				+ point.getSignature().getName());
		System.out.println("afterLog-------------参数为：" + Arrays.toString(point.getArgs()));
		System.out.println("afterLog--------------被植入的目标对象为：" + point.getTarget());
	}
	
	@AfterReturning(value = pointcut, returning = "returnValue")
	public void afterReturningLog(JoinPoint point, Object returnValue) {
		System.out.println("afterReturningLog------------返回值后通知");
		System.out.println("afterReturningLog-------------目标方法为：" + point.getSignature().getDeclaringTypeName() + "."
				+point.getSignature().getName());
		System.out.println("afterReturningLog---------------参数为：" + Arrays.toString(point.getArgs()));
		System.out.println("afterReturningLog--------------返回值为：" + returnValue);
	}
	
	@AfterThrowing(throwing = "ex", value = pointcut)
	public void afterThrowing(Throwable ex) {
		System.out.println("AfterThrowing---------------进入异常通知");
		System.out.println("AfterThrowing---------------异常信息：" + ex.getMessage());
	}
	
	@Around(pointcut)
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("around------------进入环绕通知");
		System.out.println("around--------------开始记时");
		long startTime = System.currentTimeMillis();
		Object obj = pjp.proceed();
		long endTime = System.currentTimeMillis();
		System.out.println("around------------计时结束，一共用时为：" + (endTime - startTime) + "毫秒");
		System.out.println("around------------方法运行结束");
		return obj;
	}
	
}
